/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.soundtrigger_middleware;

import android.media.soundtrigger.RecognitionConfig;
import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger.Phrase;

import android.media.soundtrigger_middleware.IInjectModelEvent;
import android.media.soundtrigger_middleware.IInjectRecognitionEvent;
import android.media.soundtrigger_middleware.IInjectGlobalEvent;
import android.media.soundtrigger_middleware.ISoundTriggerInjection;

/**
 * An injection interface for {@link android.media.soundtrigger_middleware.FakeSoundTriggerHal}.
 * To avoid deadlocks, all calls to this interface and the sub-interface it creates are oneway.
 * Calls are identified as stale via "Session" parameters.
 * The client implements this interface and registers it with
 * {@link ISoundTriggerMiddlewareService#attachMockHalInjection(ISoundTriggerInjection)}.
 * Then, the client will receive callbacks which observe mock HAL events.
 * There are two types of calls.
 * 1) Those that provide a new injection sub-interface (contains param .*Injection).
 * 2) Those that are sessioned via an injection sub-interface (contains param .*Session).
 * The new injection sub-interfaces generated by (1) can be used to trigger HAL events.
 * Some calls within (2) will invalidate the session object which they are associated with
 * (e.g. {@link soundModelUnloaded}), and will be noted as such.
 * Some calls within the injection interface (e.g. {@link IInjectModelEvent#triggerUnloadModel()})
 * will invalidate the session object they are called upon, and will be noted as such.
 * @hide
 */
oneway interface ISoundTriggerInjection {

    /**
     * Value of {@link android.media.soundtrigger.Properties#supportedModelArch} that
     * identifies the HAL as a fake HAL.
     */
    const String FAKE_HAL_ARCH = "injection";

    /**
     * Called following attachment via
     * {@link ISoundTriggerMiddlewareService#attachMockHalInjection(ISoundTriggerInjection)}.
     * Provides the client an injection interface for events which are always (globally) valid.
     * @param globalInjection - Interface used to inject global events to the fake HAL.
     * Used as a session object for further callbacks associated with the HAL globally.
     */
    void registerGlobalEventInjection(IInjectGlobalEvent globalInjection);

    /**
     * Called when the HAL has been restarted by the framework. Not called after a
     * {@link IInjectGlobalEvent#triggerRestart()}.
     * @param globalSession - The interface previously provided by a
     * {@link registerGlobalEventInjection} call which this restart is associated with.
     * Used to disambiguate stale restart events from a subsequent global session.
     */
    void onRestarted(IInjectGlobalEvent globalSession);

    /**
     * Called when the HAL has been detached by the framework.
     * @param globalSession - The interface previously provided by a
     * {@link registerGlobalEventInjection} call which this detach is associated with.
     * Used to disambiguate stale detach events from a subsequent global session.
     */
    void onFrameworkDetached(IInjectGlobalEvent globalSession);

    /**
     * Called when a client is attached to the framework. This event is not actually
     * delivered to the HAL, but is useful to understand the framework state.
     * @param token - An opaque token representing the framework client session.
     * Associated with a subsequent call to {@link onClientDetached(IBinder)}.
     * @param globalSession - The global STHAL session this attach is associated with.
     */
    void onClientAttached(IBinder token, IInjectGlobalEvent globalSession);

    /**
     * Called when a client detaches from the framework. This event is not actually
     * delivered to the HAL, but is useful to understand the framework state.
     * @param token - The opaque token returned by a previous
     * {@link onClientAttached(IBinder, IInjectGlobalEvent} call.
     */
    void onClientDetached(IBinder token);

    /**
     * Called when a sound model is loaded into the fake STHAL by the framework.
     * @param model - The model data for the newly loaded model.
     * @param phrases - The phrase data for the newly loaded model, if it is a keyphrase model.
     *                  Null otherwise.
     * @param modelInjection - Interface used to inject events associated with the newly loaded
     * model into the fake STHAL.
     * Used as a session object for further callbacks associated with this newly loaded model.
     * @param globalSession - The session object representing the global STHAL instance this load
     * is associated with.
     */
    void onSoundModelLoaded(in SoundModel model, in @nullable Phrase[] phrases,
                        IInjectModelEvent modelInjection, IInjectGlobalEvent globalSession);

    /**
     * Called when the fake STHAL receives a set parameter call from the framework on a previously
     * loaded model.
     * @param modelParam - Code of the parameter being set, see
     * {@link android.media.soundtrigger.ModelParameter}
     * @param value - Value to set the modelParam to
     * @param modelSession - Session object of the loaded model the set param call is associated
     * with.
     */

    void onParamSet(int modelParam, int value, IInjectModelEvent modelSession);


    /**
     * Called when a previously loaded model in the fake STHAL has recognition started by the
     * framework.
     * @param audioSessionToken - The audio session token passed by the framework which will be
     * contained within a received recognition event.
     * @param config - The recognition config passed by the framework for this recognition.
     * @param recognitionInjection - A new injection interface which allows the client to
     * trigger events associated with this newly started recognition.
     * @param modelSession - The session object representing the loaded model that this
     * recognition is associated with.
     */
    void onRecognitionStarted(int audioSessionToken, in RecognitionConfig config,
            IInjectRecognitionEvent recognitionInjection, IInjectModelEvent modelSession);

    /**
     * Called when a previously started recognition in the fake STHAL is stopped by the framework.
     * Not called following any calls on {@link IInjectRecognitionEvent}.
     * @param recognitionSession - The session object received via a previous call to
     * {@link recognitionStarted(int, RecognitionConfig, IInjectModelEvent,
     * IInjectRecognitionEvent} which has been unloaded.
     * This session is invalidated subsequent to this call, and no triggers will be respected.
     */
    void onRecognitionStopped(IInjectRecognitionEvent recognitionSession);

    /**
     * Called when a previously loaded model in the fake STHAL is unloaded by the framework.
     * Not called following {@link IInjectModelEvent#triggerUnloadModel()}.
     * @param modelSession - The session object received via a previous call to
     * {@link soundModelLoaded(SoundModel, Phrase[], IInjectModelEvent} which has been unloaded.
     * This session is invalidated subsequent to this call, and no triggers will be respected.
     */
    void onSoundModelUnloaded(IInjectModelEvent modelSession);

    /**
     * Called when this injection interface has been preempted by a subsequent call to
     * {@link ISoundTriggerMiddleware#attachFakeHal(ISoundTriggerInjection)}.
     * No more events will be delivered, and any further injection will be ignored.
     */
    void onPreempted();

}
